

#include "uart_service.h" // 包含串口服务头文件
#include "ring_buffer.h"

typedef struct
{
    int msg_type;
} uart_event_msg_t;

#define UART_RX_BUF_SIZE (2 * 1024)
#define UART_PACKET_TIMEOUT 100 // ms

// ------------------ GPIO初始化 ------------------
static void uart_gpio_init(cm_uart_dev_e uart)
{
    switch (uart)
    {
    case CM_UART_DEV_0:
        cm_iomux_set_pin_func(CM_IOMUX_PIN_17, CM_IOMUX_FUNC_FUNCTION1);
        cm_iomux_set_pin_func(CM_IOMUX_PIN_18, CM_IOMUX_FUNC_FUNCTION1);
        break;
    case CM_UART_DEV_1:
        cm_iomux_set_pin_func(CM_IOMUX_PIN_28, CM_IOMUX_FUNC_FUNCTION1);
        cm_iomux_set_pin_func(CM_IOMUX_PIN_29, CM_IOMUX_FUNC_FUNCTION1);
        break;
    default:
        break;
    }
}

// ------------------ 串口回调 ------------------
static void uart_event_callback(void *param, uint32_t type)
{
    uart_ctx_t *ctx = (uart_ctx_t *)param;
    if (!ctx)
        return;

    if (type & CM_UART_EVENT_TYPE_RX_ARRIVED)
        osSemaphoreRelease(ctx->sem);

    if (type & (CM_UART_EVENT_TYPE_RX_OVERFLOW | CM_UART_EVENT_TYPE_RX_FLOWCTRL))
    {
        if (ctx->event_queue)
        {
            uart_event_msg_t msg = {.msg_type = type};
            osMessageQueuePut(ctx->event_queue, &msg, 0, 0);
        }
    }
}

// ------------------ 异常事件线程 ------------------
static void uart_event_task(void *arg)
{
    uart_ctx_t *ctx = (uart_ctx_t *)arg;
    uart_event_msg_t msg;

    while (1)
    {
        if (osMessageQueueGet(ctx->event_queue, &msg, NULL, osWaitForever) == osOK)
        {
            if (msg.msg_type & CM_UART_EVENT_TYPE_RX_OVERFLOW)
                cm_log_printf(0, "UART%d RX_OVERFLOW\n", ctx->uart);
            if (msg.msg_type & CM_UART_EVENT_TYPE_RX_FLOWCTRL)
                cm_log_printf(0, "UART%d RX_FLOWCTRL\n", ctx->uart);
        }
    }
}

// ------------------ 数据接收线程 ------------------
// ------------------ 数据接收线程（逐字打印） ------------------
// ------------------ 数据接收线程（读1个发1个） ------------------
static void uart_rx_task(void *arg)
{
    uart_ctx_t *ctx = (uart_ctx_t *)arg;
    uint16_t single_len; // 仅需记录单次读取长度（固定为1）
    uint8_t rx_byte;     // 单个字节接收缓冲区（无需大数组）

    memset(&rx_byte, 0, sizeof(rx_byte));

    while (1)
    {
        // 等待串口接收信号量（阻塞直到有数据）
        osSemaphoreAcquire(ctx->sem, osWaitForever);

        // 循环读取：每次只读1个字节，读成功就立即发送
        while (1)
        {
            // 单次仅读取1个字节，超时100ms
            single_len = cm_uart_read(ctx->uart, &rx_byte, 1, 100);
            if (single_len > 0)
            {
                // // 读成功：立即将这个字节发回串口
                // // cm_uart_write(ctx->uart, &rx_byte, 1, 100);
                // // 打印当前接收的字节（十六进制格式）
                // cm_log_printf(0, "UART%d RX: %02X\n", ctx->uart, rx_byte);
                ringbuf_push(uart0_ringbuf, rx_byte); // 写入缓冲
            }
            else
            {
                // 读超时（无更多数据），退出本次接收循环
                break;
            }
        }
    }
}
// ------------------ 串口初始化 ------------------
void uart_ctx_init(uart_ctx_t *ctx, cm_uart_dev_e uart, uint32_t baud)
{
    ctx->uart = uart;
    ctx->baudrate = baud;
    ctx->rx_buf = cm_malloc(UART_RX_BUF_SIZE);
    ctx->sem = osSemaphoreNew(1, 0, NULL);
    ctx->event_queue = osMessageQueueNew(10, sizeof(uart_event_msg_t), NULL);

    uart_gpio_init(uart);

    // 注册事件
    cm_uart_event_t event = {
        CM_UART_EVENT_TYPE_RX_ARRIVED | CM_UART_EVENT_TYPE_RX_OVERFLOW,
        ctx,
        uart_event_callback};
    cm_uart_register_event(uart, &event);

    // 配置并打开串口
    cm_uart_cfg_t config = {CM_UART_BYTE_SIZE_8, CM_UART_PARITY_NONE, CM_UART_STOP_BIT_ONE,
                            CM_UART_FLOW_CTRL_NONE, baud, 0, 0, 0, 0};
    cm_uart_open(uart, &config);

    // 创建接收线程
    osThreadAttr_t rx_attr = {.name = "uart_rx", .priority = osPriorityNormal, .stack_size = 2048};
    ctx->rx_thread = osThreadNew(uart_rx_task, ctx, &rx_attr);

    // 创建事件线程
    osThreadAttr_t ev_attr = {.name = "uart_event", .priority = osPriorityNormal, .stack_size = 1024};
    ctx->event_thread = osThreadNew(uart_event_task, ctx, &ev_attr);

    // 打印初始化信息
    cm_log_printf(0, "UART%d init done, baudrate: %d\n", uart, baud);
}
